package project.jsf;

import java.util.List;
import project.entity.Evento;
import project.jsf.util.JsfUtil;
import project.jsf.util.PaginationHelper;
import project.ejbs.EventoFacade;

import java.io.Serializable;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.mail.MessagingException;
import project.ejbs.AutorFacade;
import project.ejbs.EmailFacade;
import project.ejbs.Session;
import project.ejbs.SubmissaoFacade;
import project.entity.Autor;
import project.entity.Papel.Perfil;
import project.entity.Submissao;

@ManagedBean(name = "eventoController")
@SessionScoped
public class EventoController implements Serializable {

    private Evento current;
    private DataModel items = null;
    @EJB
    private Session sessao;
    @EJB
    private project.ejbs.EventoFacade ejbFacade;
    @EJB
    private SubmissaoFacade submissaoEjbFacade;
    private PaginationHelper pagination;
    private int selectedItemIndex;
    @EJB
    private project.ejbs.EditorFacade editorEjbFacade;
    @EJB
    private AutorFacade autorEjbFacade;
    @EJB
    private EmailFacade ejbEmail;
    private DataModel submissoes = null;

    public EventoController() {
    }
    
    public Evento getSelected() {
        if (current == null) {
            current = new Evento();
            selectedItemIndex = -1;
        }
        return current;
    }

    private EventoFacade getFacade() {
        return ejbFacade;
    }

    public PaginationHelper getPagination() {
        if (pagination == null) {
            pagination = new PaginationHelper(10) {

                @Override
                public int getItemsCount() {
                    return getFacade().count();
                }

                @Override
                public DataModel createPageDataModel() {
                    return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
                }
            };
        }
        return pagination;
    }

    public String prepareList() {
        recreateModel();
        return "List";
    }

    public String prepareView() {
        current = (Evento) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        sessao.setIdEvento(current.getIdEvento());
        recreateModel();
        return "View";
    }

    public String prepareCreate() {
        current = new Evento();
        selectedItemIndex = -1;
        return "Create";
    }

    public String create() {
        try {
            if (current.getDataFimSubmissoes().before(new Date())){
                JsfUtil.addErrorMessage("Data de fim de submissões inválida!");
            }
            if (current.getDataRealizacao().after(current.getDataFimRevisoes()) && current.getDataFimRevisoes().after(current.getDataFimSubmissoes())){
                current.setEditor(editorEjbFacade.find(sessao.getUsername()));
                getFacade().create(current);

                List <Autor> listaAutores = autorEjbFacade.findAll();

                for (Autor autor : listaAutores) {
                    try {
                        ejbEmail.enviar(autor.getEmail() , "Novo Evento", "Caro/a " + autor.getpNome() + " " + autor.getuNome() + ",\nO novo evento \"" + current.getTitulo() + "\" foi criado onde voce pode submeter artigos até à data: " + current.getDataFimSubmissoes() + ".\n\nObrigado.");
                    } catch (MessagingException ex) {
                        Logger.getLogger(RevisorController.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }

                JsfUtil.addSuccessMessage("Evento criado com sucesso.");
                recreateModel();
                return prepareList();
            }
            JsfUtil.addErrorMessage("Erro nas datas, verifique as datas das entregas e da realização.");
            return null;
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, "Ocurreu um erro ao tentar criar o evento");
            return null;
        }
    }

    public String prepareEdit() {
        current = (Evento) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "Edit";
    }

    public String update() {
        try {
            getFacade().edit(current);
            JsfUtil.addSuccessMessage("Evento actualizado com sucesso.");
            return "View";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, "Ocurreu um erro ao tentar editar o evento");
            return null;
        }
    }

    public DataModel getItems() {
        if (items == null) {
            items = getPagination().createPageDataModel();
        }
        return items;
    }

    private void recreateModel() {
        items = null;
        submissoes = null;
    }

    public String next() {
        getPagination().nextPage();
        recreateModel();
        return "List";
    }

    public String previous() {
        getPagination().previousPage();
        recreateModel();
        return "List";
    }

    public SelectItem[] getItemsAvailableSelectMany() {
        return JsfUtil.getSelectItems(ejbFacade.findAll(), false);
    }

    public SelectItem[] getItemsAvailableSelectOne() {
        return JsfUtil.getSelectItems(ejbFacade.findAll(), true);
    }
    
    public boolean isDono(String editor){
        try{
            String username = sessao.getUsername();
            return editor.equals(username);
        } catch(Exception e){
            return false;
        }
    }

    public boolean isEditor(){
        try{
            return sessao.getPapel().equals(Perfil.Editor);
        } catch (Exception e){
            return false;
        }
    }

    /**
     * @return the submissoes
     */
    public DataModel getSubmissoes() {
        if (submissoes == null) {
            submissoes = createSubmissaoDataModel();
        }
        return submissoes;
    }
    
    public DataModel createSubmissaoDataModel() {
        try {
            if (sessao.getPapel().equals(Perfil.Editor) && isDono(getSelected().getEditor().getUsername())){
                return new ListDataModel((List)(ejbFacade.find(sessao.getIdEvento()).getSubmissoes()));
            } else if (sessao.getPapel().equals(Perfil.Autor)){
                return new ListDataModel(submissaoEjbFacade.getSubmissoesAutor(current, sessao.getUsername()));
            }
            return new ListDataModel();
        } catch (Exception e) {
            return new ListDataModel();
        }
        
    }
    
    public boolean isAutor(){
        try{
            return sessao.getPapel().equals(Perfil.Autor);
        } catch (Exception e){
            return false;
        }
    }
    
    public boolean podeCriarSubmissao(Evento evento){
        return isAutor() && evento.getDataFimSubmissoes().after(new Date());
    }
    
    public boolean podeRevisoes(Evento evento){
        return isDono(evento.getEditor().getUsername()) && evento.getDataFimRevisoes().after(new Date());
    }
    
    public boolean editarSubmissao(Submissao submissao){
        return isDono(submissao.getAutor().getUsername()) && submissao.getEvento().getDataFimSubmissoes().after(new Date());
    }
    
    @FacesConverter(forClass = Evento.class)
    public static class EventoControllerConverter implements Converter {

        public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
            if (value == null || value.length() == 0) {
                return null;
            }
            EventoController controller = (EventoController) facesContext.getApplication().getELResolver().
                    getValue(facesContext.getELContext(), null, "eventoController");
            return controller.ejbFacade.find(getKey(value));
        }

        java.lang.Long getKey(String value) {
            java.lang.Long key;
            key = Long.valueOf(value);
            return key;
        }

        String getStringKey(java.lang.Long value) {
            StringBuffer sb = new StringBuffer();
            sb.append(value);
            return sb.toString();
        }

        public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
            if (object == null) {
                return null;
            }
            if (object instanceof Evento) {
                Evento o = (Evento) object;
                return getStringKey(o.getIdEvento());
            } else {
                throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + EventoController.class.getName());
            }
        }
    }
}
